package com.cowain.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.lang.tree.parser.NodeParser;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cowain.base.core.domain.TreeSelect;
import com.cowain.base.core.domain.dto.SysMenuDto;
import com.cowain.base.core.domain.entity.SysMenuEntity;
import com.cowain.base.core.domain.vo.SysMenuVo;
import com.cowain.system.mapper.SysMenuMapper;
import com.cowain.system.service.SysMenuService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author songxz
 * @date 2022/11/9
 */
@Slf4j
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenuEntity> implements SysMenuService {

    /**
     * 菜单新增
     *
     * @param menu
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean insertMenu(SysMenuEntity menu) {
        return this.save(menu);
    }

    /**
     * 菜单修改
     *
     * @param menu
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateMenu(SysMenuEntity menu) {
        return this.updateById(menu);
    }

    /**
     * 菜单删除
     *
     * @param menuId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteMenuById(Long menuId) {
        return this.removeById(menuId);
    }

    /**
     * 查询当前用户的菜单
     *
     * @param menu
     * @return
     */
    @Override
    public List<SysMenuDto> selectMenuList(SysMenuVo menu) {
        List<SysMenuDto> dtoList = null;
        List<SysMenuEntity> list = this.list();
        if (CollectionUtil.isNotEmpty(list)) {
            dtoList = BeanUtil.copyToList(list, SysMenuDto.class);
        }
        return dtoList;
    }

    /**
     * 查询单个信息
     *
     * @param menuId
     * @return
     */
    @Override
    public SysMenuEntity selectMenuById(Long menuId) {
        return this.getById(menuId);
    }

    /**
     * 获取菜单下拉树列表
     *
     * @param menus
     * @return
     */
    @Override
    public List<Tree<Long>> buildMenuTreeSelect(List<SysMenuDto> menus) {
//        List<SysMenuDto> menuTrees = buildMenuTree(menus);
        TreeNodeConfig config=new TreeNodeConfig();
        config.setIdKey("menuId");
        config.setParentIdKey("parentId");
        List<Tree<Long>> list = TreeUtil.build(menus,0L,config,(object, tree) -> {
            tree.setId(object.getMenuId());//必填属性
            tree.setParentId(object.getParentId());//必填属性
            tree.setName(object.getMenuName());
            tree.putExtra("status",1);
        });
//        return menuTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
        return list;
    }

    /**
     * 构建前端所需要树结构
     *
     * @param menus 菜单列表
     * @return 树结构列表
     */
    @Override
    public List<SysMenuDto> buildMenuTree(List<SysMenuDto> menus) {
        List<SysMenuDto> returnList = new ArrayList<>();
        List<Long> tempList = menus.stream().map(s -> s.getMenuId()).collect(Collectors.toList());
        Iterator<SysMenuDto> iterator = menus.iterator();
        while (iterator.hasNext()) {
            SysMenuDto menu = iterator.next();
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(menu.getParentId())) {
                recursionFn(menus, menu);
                returnList.add(menu);
            }
        }
        if (returnList.isEmpty()) {
            returnList = menus;
        }
        return returnList;
    }

    /**
     * 递归列表
     *
     * @param list
     * @param t
     */
    private void recursionFn(List<SysMenuDto> list, SysMenuDto t) {
        // 得到子节点列表
        List<SysMenuDto> childList = getChildList(list, t);
        t.setChildren(childList);
        for (SysMenuDto tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<SysMenuDto> getChildList(List<SysMenuDto> list, SysMenuDto t) {
        List<SysMenuDto> tlist = new ArrayList<>();
        Iterator<SysMenuDto> it = list.iterator();
        while (it.hasNext()) {
            SysMenuDto n = it.next();
            if (n.getParentId().equals(t.getMenuId())) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<SysMenuDto> list, SysMenuDto t) {
        return getChildList(list, t).size() > 0;
    }
}
